﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace RVBike
{
	/// <summary>
	/// Interaction logic for RoomPage.xaml
	/// </summary>
	public partial class RoomPage : UserControl, ISwitchable
	{
        private GameSetting _setting = null;
        private RVRoom _room = null;
        private bool _ready = false;
		
		public RoomPage()
		{
			this.InitializeComponent();

            // Initialize multilanguage strings
            dummyPlayers.Content = MultiLanguage.Instance().Translate("players");
            btn_leave.Content = MultiLanguage.Instance().Translate("leave");
		}

        private void RegisterCallback()
        {
            RVGameController.Instance().JoinRoomHandler += OnReceiveJoinRoom;
            RVGameController.Instance().LeaveRoomHandler += OnReceiveLeaveRoom;
            RVGameController.Instance().ClientStateChangeHandler += OnReceiveCSChanged;
            RVGameController.Instance().QuitRoomHandler += OnReceiveQuitRoom;
            RVGameController.Instance().GameStartHandler += OnReceiveGameStart;
        }

        private void UnregisterCallback()
        {
            RVGameController.Instance().JoinRoomHandler -= OnReceiveJoinRoom;
            RVGameController.Instance().LeaveRoomHandler -= OnReceiveLeaveRoom;
            RVGameController.Instance().ClientStateChangeHandler -= OnReceiveCSChanged;
            RVGameController.Instance().QuitRoomHandler -= OnReceiveQuitRoom;
            RVGameController.Instance().GameStartHandler -= OnReceiveGameStart;
        }

		private void OnButtonClick(object sender, System.Windows.RoutedEventArgs e)
        {
        	// TODO: Add event handler implementation here.
			if (sender == btn_leave)
			{
                RVGameController.Instance().LeaveRoom();
                UnregisterCallback();

				RVSwitcher.Switch(new MultiplePlayerPage());
			}
			else if (sender == btn_ready)
			{
                if (RVGameController.Instance().Master)
                {
                    if (!RVGameController.Instance().SendGameStart())
                    {
                        // Status is not sync!! update room state again
                        _room = RVGameController.Instance().QueryRoomInformation();
                        UpdatePage();
                    }
                }
                else
                {
                    if (_ready)
                    {
                        btn_ready.Content = MultiLanguage.Instance().Translate("ready");
                        RVGameController.Instance().UpdateState(RVNetworkEnv.CLIENT_STATE_NOT_READY, 0.0f, "0,0");
                    }
                    else
                    {
                        btn_ready.Content = MultiLanguage.Instance().Translate("cancel");
                        RVGameController.Instance().UpdateState(RVNetworkEnv.CLIENT_STATE_READY, 0.0f, "0,0");
                    }
                }

                _ready = !_ready;
			}
        }
		
		private void UpdatePage()
		{
			// Disable all contorls
            if (_setting == null || _room == null)
            {
                this.IsEnabled = false;
                return;
            }

            txt_user_name.Text = UserSetting.Instance().UserName;
            mapImage.Source = new BitmapImage(new Uri(_setting.SelectedStage.CoverPath));
            mapName.Content = _setting.SelectedStage.DisplayName;
            txt_info.Text = _setting.SelectedStage.Description;

            switch (_setting.GameMode)
            {
                case GameMode.Normal: roomMode.Content = MultiLanguage.Instance().Translate("normal_mode"); break;
                case GameMode.Mileage: roomMode.Content = MultiLanguage.Instance().Translate("mileage_mode"); break;
                case GameMode.Time: roomMode.Content = MultiLanguage.Instance().Translate("time_mode"); break;
            }

			roomName.Content = _room.RoomName;

            // Update client list
            ListBox_player.Items.Clear();
            foreach (RVClientState cs in _room.Clients)
            {
                ListBox_player.Items.Add(String.Format("{0} ({1})", cs.Name, cs.State));
            }

            if (RVGameController.Instance().Master)
            {
                btn_ready.Content = MultiLanguage.Instance().Translate("start");

                int readyCount = 1; // count myself first
                foreach (RVClientState cs in _room.Clients)
                {
                    if (cs.State == RVNetworkEnv.CLIENT_STATE_READY) ++readyCount;
                }

                if (readyCount == _room.Clients.Count)
                {
                    btn_ready.IsEnabled = true;
                }
                else
                {
                    btn_ready.IsEnabled = false;
                }
            }
        }

        private void OnReceiveJoinRoom(string name, string ip)
        {
            Dictionary<string, string> info = new Dictionary<string, string>();
            info.Add(RVNetworkEnv.CLIENT_IP, ip);
            info.Add(RVNetworkEnv.USER_NAME, name);
            info.Add(RVNetworkEnv.CLIENT_STATE, RVNetworkEnv.CLIENT_STATE_NOT_READY);

            RVClientState cs = new RVClientState(info);
            _room.Clients.Add(cs);

            ListBox_player.Dispatcher.Invoke(new Action(() =>
            {
                ListBox_player.Items.Add(String.Format("{0} ({1})", cs.Name, cs.State));
            }));

            if (RVGameController.Instance().Master)
            {
                int readyCount = 1; // count myself first
                foreach (RVClientState cs2 in _room.Clients)
                {
                    if (cs2.State == RVNetworkEnv.CLIENT_STATE_READY) ++readyCount;
                }

                btn_ready.Dispatcher.Invoke(new Action(() =>
                {
                    btn_ready.IsEnabled = (readyCount == _room.Clients.Count);
                }));
            }
        }

        private void OnReceiveLeaveRoom(string ip)
        {
            int index = 0;
            for (; index < _room.Clients.Count; ++index)
            {
                if (_room.Clients[index].IP == ip)
                {
                    break;
                }
            }

            if (index < _room.Clients.Count)
            {
                _room.Clients.RemoveAt(index);

                ListBox_player.Dispatcher.Invoke(new Action(() =>
                {
                    ListBox_player.Items.RemoveAt(index);
                }));

                if (RVGameController.Instance().Master)
                {
                    int readyCount = 1; // count myself first
                    foreach (RVClientState cs2 in _room.Clients)
                    {
                        if (cs2.State == RVNetworkEnv.CLIENT_STATE_READY) ++readyCount;
                    }

                    btn_ready.Dispatcher.Invoke(new Action(() =>
                    {
                        btn_ready.IsEnabled = (readyCount == _room.Clients.Count);
                    }));
                }
            }
            else
            {
                // something wrong
                System.Diagnostics.Trace.WriteLine("Receive leave room message but cannot find such user!!");
            }
        }

        private void OnReceiveCSChanged(string ip, float mileage, string state, string gps)
        {
            int index = 0;
            for (; index < _room.Clients.Count; ++index)
            {
                if (_room.Clients[index].IP == ip)
                {
                    break;
                }
            }

            if (index < _room.Clients.Count)
            {
                _room.Clients[index].Mileage = mileage;
                _room.Clients[index].State = state;

                RVClientState cs = _room.Clients[index];
                ListBox_player.Dispatcher.Invoke(new Action(() =>
                {
                    ListBox_player.Items[index] = String.Format("{0} ({1})", cs.Name, cs.State);
                }));

                if (RVGameController.Instance().Master)
                {
                    int readyCount = 1; // count myself first
                    foreach (RVClientState cs2 in _room.Clients)
                    {
                        if (cs2.State == RVNetworkEnv.CLIENT_STATE_READY) ++readyCount;
                    }

                    btn_ready.Dispatcher.Invoke(new Action(() =>
                        {
                            btn_ready.IsEnabled = (readyCount == _room.Clients.Count);
                        }));
                }
            }
            else
            {
                // something wrong
                System.Diagnostics.Trace.WriteLine("Receive state update message but cannot find such user!!");
            }
        }

        private void OnReceiveQuitRoom()
        {
            RVGameController.Instance().LeaveRoom();
            UnregisterCallback();
            Dispatcher.Invoke(new Action(() =>  RVSwitcher.Switch(new MultiplePlayerPage())));
        }

        private void OnReceiveGameStart()
        {
            RVGameController.Instance().UpdateState(RVNetworkEnv.CLIENT_STATE_LOADING, 0.0f, "0,0");
            UnregisterCallback();
            Dispatcher.Invoke(new Action(() => RVSwitcher.Switch(new MainGamePage(), _setting)));
        }
		
        #region ISwitchable Members
        public void UtilizeState(object state)
        {
            _setting = state as GameSetting;

            _room = RVGameController.Instance().QueryRoomInformation();
            RegisterCallback();
            UpdatePage();
        }

        public void WindowLocationChanged(double x, double y)
        {
        }
        #endregion
	}
}